The Spring framework is a framework for writing Java applications. Spring Framework has always been there since I started Java programming which helped me a lot with initializing the objects at the beginning of an application. By having these initializations made my coding life simpler as required objects were always available for me. By the way, the initialization work is not everything that Spring Framework is offering though. It also supports setting up the web environment fashionably “easy” in Java. Honestly though, strictly from my experience, setting a web environment wasn’t all that easy for me in Spring (configurations are too strict). Well even with all this complexity, we refer to Spring Framework as a “lightweight” container because it’s “light” compared to other J2EE containers (like EJB). The “lightweight” side of Spring Framework provides the modular approach with handling injections, web applications, and data access/integration, etc. From my personal experience, I find initial setup to be quite time consuming. However, once you have everything setup and ready to go, it makes up for a lot of those efforts you put initally because attaching/detaching things to the Spring actually becomes pretty simple down the roads.
I come across a few developers who still think Spring is basically a Dependency Injection tool to initialize objects. The statement isn’t entirely incorrect, but it definitely isn’t correct. Spring does vastly more tasks than just initializing the objects. Let me introduce some of the major jobs Spring is capable of including the Dependency Injection. The list is compiled from my own work experiences so I may miss some key factors which I have not yet come across. Please comment below if I did miss any important concept in Spring.
"Design your objects so that they rely on an outside force to supply them with what they need, with the expectation that these dependencies are always injected before anybody asks them to start doing their usual jobs."
Dependency Injection is undoubtedly one of the key concepts in Spring Framework. You can provide information from the external source such as XML file where the file can be responsible for providing the initialization of all the objects required for your application. You do not need to create objects individually anymore instead you can define how they should be created and IoC container takes care of creating the objects for you. For more details on “how to use it”, I covered the usage by comparing between Spring and Guice DI in my previous post where I explained with examples on how to use it as well. I would argue that the big (if not biggest) benefit of dependency injection is that your code becomes loosely coupled. Therefore you can attach and detach this behaviour of injection quite easily.
"The application controls the framework, not the framework controls the application."
In Spring Framework, loose coupling is achieved through “Inversion of Control”. A class accepts the objects it requires from an injector object instead of creating the objects directly. You can read upon Martin Fowler’s article for more details on Inversion of Controls.
I have seen many people avoid Spring due to the XML bindings. Keep in mind that Spring is entirely capable of using just the annotation like the Google Guice for your DI work. You do not need to require the XML to inject in Spring in later versions. Please check on my GitHub code on how it handles it, specifically on @Autowire annotation.
Spring MVC (Model-View-Controller) web framework is probably the most popular and well-known framework for Java web applications development. You can add extensions for building web applications which provide a great alternative to web frameworks such as Struts or other over-engineered or less popular web frameworks. You can use servlets combined with JSPs to create an interactive website that is easy to manage in MVC pattern in mind. “Model” is done through Java where we can be specific on how the item is going to have. It would have the specifics of the model such as id, name, desc, or whatever the object needs. “View” is written most commonly in JSPs (for Java programming) where the web application will be viewed by the users. This could be other than JSP if you want. However, it is probably the cleanest to use JSP for Java programming though as bindings between MVC is pretty straightforward for JSP. “Control” is handled in Java where you can setup the mappings and their services and it is responsible for controlling the web application. These “control” configurations/mappings/models/controls can easily be enabled by loading appropriate Spring Framework annotations.
Keep this in mind that these controllers are going to be served as servlets which extend the capabilities of the server. Spring is essentially making it easy for setting the entire web stack compared to setting up using the plain Java servlet library.
To deploy and run JavaServer Pages remotely, a compatible web server with a servlet container, such as Apache Tomcat or Jetty, is normally required. The best example of how web pages are served in Spring MVC is best described in Spring website from my experience. They provide a very simple case of loading “hello world” which I highly recommend you to try it out.
Spring Framework 5 also delivers a new “reactive” web stack called, Spring WebFlux, which is offered side-by-side with the traditional Spring MVC web stack. What is “reactive”? You might ask. In plain terms, “reactive” programming is about non-blocking applications that are asynchronous and event-driven and require a small number of threads to scale vertically (i.e. within the JVM) rather than horizontally (i.e. through clustering). Reactive programming also leads to a major shift from imperative to a declarative async composition of logic. It is comparable to writing blocking code vs using the CompletableFuture
from Java 8 to compose follow-up actions via lambda expressions. For a longer introduction check the blog series “Notes on Reactive Programming” by Dave Syer.
Typically in order to handle data, modern Java provides a plain-vanilla JDBC library which connects to the datasource then run through prepare/execute of the DB statement and you are responsible for the cleaning up on those connections. They can get overly complicated and verbose for such a simple task. The Data Access Object (DAO) support in Spring (or any other DB framework) is aiming to make it easy to work with data access layers such as JDBC. Spring provides a template class called JdbcTemplate
that makes it easy to work with SQL relational databases along with JDBC. The JdbcTemplate takes care of resource acquisition, connection management, exception handling, and general error checking, and many others for you. All you have to do is focus on the task at hand.
I will show you a simple and quick example of how they all work together and what I really mean.
Content of an example config.properties:
Then through your Config.class, you can initialize the objects (called beans in Spring):
To initialize these beans, run: new AnnotationConfigApplicationContext(AppConfig.class)
. Once we have the data source loaded into the application DAO object can load it up something like this:
Then you can freely run the select/update/insert queries depending on your need. For example, getJdbcTemplate().queryForObject(sql, BeanPropertyRowMapper.newInstance(Customer.class), id);
. Customer.class is where it belongs to the “Model”. Here we are assigning the SQL results as a Customer.class objects to be used. You can literally map it into any kind of expected output depending on your query, for example, Integer.class.
This isn’t everything. This is only a fraction of whats in Spring DB handling, just to show you how to interact with DB (Oracle in the above example). You can also extend the application using Spring so it uses Hibernate instead of Spring JdbcTemplate. You can hook it with MyBatis instead JdbcTemplate for DB handling. Anyways, I already find Spring’s JdbcTemplate pretty convenient for most of the time. These alternate solutions may simplify the data related tasks when it comes too complex to manage queries. The best comparisons between these options I have witnessed so far is found here.
Aspect Oriented Programming (AOP) framework is another important component of the Spring. The key unit of modularity in OOP is the class, whereas in AOP the unit of modularity is the “aspect”. DI helps you decouple your application objects from each other, while AOP helps you decouple cross-cutting concerns from the objects that they affect. The functions that span multiple points of an application are essentially called cross-cutting concerns and these cross-cutting concerns are conceptually separate from the application’s business logic. There are various common good examples of aspects including logging, declarative transaction management, security, caching, etc.
The AOP module of Spring Framework provides an aspect-oriented programming implementation allowing you to define method-interceptors and pointcuts to cleanly decouple code that implements functionality that should be separated. For example, when a method is executed, you can add extra functionality before or after the method execution.
Spring supports the @AspectJ annotation style approach and the schema-based approach to implement custom aspects.
Approach | Description |
---|---|
XML Schema-based | Aspects are implemented using the regular classes along with XML based configuration. |
@AspectJ based | @AspectJ refers to a style of declaring aspects as regular Java classes annotated with Java 5 annotations. |
For detailed explanation with great code examples on AOP, I recommend reading over this page.
Obviously, if you aren’t building a full-blown application, for example, specific libraries, then Spring probably isn’t even required. It is really meant for the enterprise level application where these setups can lead to a wormholes and spaghetti code. Spring will help make your application more organized and less coupled. However, if it’s used on a smaller scale application, Spring can certainly add stresses to the application and makes the code complicated for no good reason. You need to decide where and when the Spring is applicable to an application. The answer is not always clear though.